iOS页面传值 - 闭包传值

页面传值是开发中必不可少的业务需求,经常会有在 B 页面干完一些事情之后告诉 A 页面或者传值到 A 页面。这种需求通常使用属性、闭包、代理、单例、通知几种方式进行实现,下面我们来了解 iOS 页面传值中的闭包传值。

闭包传值的实现思路如下:

1
2
3
4
5
6
7
8
9
10
11
1. 在B中声明一个block
typealias TestBlock = (String)->()
2. 持有一个block变量
var blo: TestBlock?
3. 调用
self.blo?("It is block test")
4. 在A中需要接受值的地方
let b = B()
b.blo = {str in
print("test block---\\(str)")
}

下面我们就以让第二个界面中的 lable 显示第一个界面 textField 中的文本这个功能为例,了解属性传值的具体实现。首先创建一个 RootViewController 和一个 DetailViewController,在 DetailViewController 中声明一个闭包,并将其声明为 DetailViewController 的属性:

1
2
3
4
5
6
7
8
9
10
11
typealias passingValueBlock = (lable: UILabel) -> Void
class DetailViewController: UIViewController {
var passingValue: passingValueBlock?
override func viewDidLoad() {
super.viewDidLoad()
}
}

然后创建一个 UILabel 用于展示接收到的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class DetailViewController: UIViewController {
var passingValue: passingValueBlock?
override func viewDidLoad() {
super.viewDidLoad()
let frame = CGRectMake(20, 100, self.view.frame.size.width-40, 100)
let lable = UILabel(frame: frame)
lable.font = UIFont.systemFontOfSize(20)
lable.backgroundColor = UIColor.whiteColor()
lable.numberOfLines = 0
self.view.addSubview(lable)
self.view.backgroundColor = UIColor.greenColor()
}
}

下面,调用 passingValue 这个闭包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class DetailViewController: UIViewController {
var passingValue: passingValueBlock?
override func viewDidLoad() {
super.viewDidLoad()
let frame = CGRectMake(20, 100, self.view.frame.size.width-40, 100)
let lable = UILabel(frame: frame)
self.passingValue!(lable: lable)
lable.font = UIFont.systemFontOfSize(20)
lable.backgroundColor = UIColor.whiteColor()
lable.numberOfLines = 0
self.view.addSubview(lable)
self.view.backgroundColor = UIColor.greenColor()
}
}

现在我们回到 RootViewController 中,创建一个 UITextField 用于接收输入的文本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class RootViewController: UIViewController {
var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let frame = CGRectMake(20, 100, self.view.bounds.width-40, 40)
self.textField = UITextField(frame: frame)
self.textField.borderStyle = .RoundedRect
self.view.addSubview(textField)
self.view.backgroundColor = UIColor.redColor()
}
}

添加 button 和手势,当点击 button 时响应相应方法进行视图间的切换完成视图间的传值,当轻触视图任意位置时取消键盘的第一响应:

1
2
3
4
5
6
7
8
9
10
let tap = UITapGestureRecognizer(target: self, action: #selector(RootViewController.handleTap(_:)))
self.view.addGestureRecognizer(tap)
let pushButton = UIButton(type: .Custom)
pushButton.frame = CGRectMake(0, 0, 120, 30)
pushButton.center = self.view.center
pushButton.backgroundColor = UIColor.grayColor()
pushButton.setTitle("Block传值", forState: .Normal)
pushButton.addTarget(self, action: #selector(RootViewController.handlePush(_:)), forControlEvents: .TouchUpInside)
self.view.addSubview(pushButton)

下面实现 button 和手势对应的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func handleTap(tap: UITapGestureRecognizer) {
self.textField.resignFirstResponder()
} //转跳到DetailViewController
func handlePush(sender: UIButton) {
let detailVC = DetailViewController()
detailVC.passingValue = { (lable: UILabel) -> Void in
lable.text = self.textField.text
} //调用Closure传值给DetailViewController
self.presentViewController(detailVC, animated: true) {
print("转跳成功")
} //转跳到DetailViewController
}

这样我们就利用闭包传值的方式,实现让第二个界面中的 lable 显示第一个界面 textField 中的文本。